package com.gqz.equip.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.gqz.common.core.domain.RequestForm;
import com.gqz.common.core.utils.poi.ExcelUtil;
import com.gqz.common.core.utils.query.QueryMapperUtil;
import com.gqz.equip.app.entity.EnStockTaskEntity;
import com.gqz.equip.app.entity.EnStockTaskOperatePtEntity;
import com.gqz.equip.app.entity.TEnWzEquipEntity;
import com.gqz.equip.app.mapper.EnStockTaskMapper;
import com.gqz.equip.app.mapper.EnStockTaskOperateMapper;
import com.gqz.equip.app.mapper.TEnWzEquipMapper;
import com.gqz.equip.app.mapstruct.EnStockTaskMapstruct;
import com.gqz.equip.app.mapstruct.TEnWzEquipMapstruct;
import com.gqz.equip.entity.EnStockEquipDefectEntity;
import com.gqz.equip.entity.EnStockTaskEquipEntity;
import com.gqz.equip.entity.EnWzEquipLogEntity;
import com.gqz.equip.entity.TEnWzSblxEntity;
import com.gqz.equip.mapper.EnStockEquipDefectMapper;
import com.gqz.equip.mapper.EnStockTaskEquipMapper;
import com.gqz.equip.mapper.EnWzEquipLogMapper;
import com.gqz.equip.mapper.TEnWzSblxMapper;
import com.gqz.equip.mapstruct.EnStockEquipDefectMapstruct;
import com.gqz.equip.mapstruct.EnStockTaskEquipMapstruct;
import com.gqz.equip.service.ITEnStockTaskEquipService;
import com.gqz.equip.service.ITEnStockTaskService;
import com.gqz.equip.utils.DateUtils;
import com.gqz.equip.vo.*;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 能源-盘点任务 业务逻辑实现层ServiceImpl
 *
 * @Version 1.0
 * @Author input you name
 */
@Service
@Slf4j
public class TEnStockTaskServiceImpl extends ServiceImpl<EnStockTaskMapper, EnStockTaskEntity> implements ITEnStockTaskService {

    @Autowired
    private ITEnStockTaskEquipService equipService;

    @Resource
    private EnStockTaskMapstruct mapstruct;

    @Resource
    private EnStockTaskEquipMapstruct equipMapstruct;

    @Resource
    private TEnWzEquipMapstruct wzEquipMapstruct;

    @Resource
    private EnStockTaskEquipMapper taskEquipMapper;

    @Resource
    private EnStockTaskOperateMapper taskOperateMapper;

    @Resource
    private TEnWzEquipMapper wzEquipMapper;

    @Resource
    private EnStockEquipDefectMapper equipDefectMapper;

    @Resource
    private EnStockEquipDefectMapstruct equipDefectMapstruct;

    @Resource
    private EnWzEquipLogMapper equipLogMapper;

    @Resource
    private TEnWzSblxMapper sblxMapper;
    @Resource
    private EnStockTaskMapper enStockTaskMapper;

    @Override
    public List<EnStockTaskVo> getById(String id) {
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.eq(EnStockTaskEntity::getId, id);
        queryWrapper.selectAll(EnStockTaskEntity.class);
        List<EnStockTaskEntity> entities = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(entities)) {
            return mapstruct.toVos(entities);
        }
        return new ArrayList<>();
    }

    @Override
    public List<EnStockTaskVo> getByTaskNo(String taskNo) {
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.eq(EnStockTaskEntity::getTaskNo, taskNo);
        queryWrapper.selectAll(EnStockTaskEntity.class);
        List<EnStockTaskEntity> entities = baseMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(entities)) {
            return mapstruct.toVos(entities);
        }
        return new ArrayList<>();
    }

    @Override
    public Page<EnStockTaskVo> page(RequestForm<EnStockTaskVo> requestForm) {
        EnStockTaskEntity entity = mapstruct.toEntity(requestForm.getEntity());
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = QueryMapperUtil.initQueryWrapper(entity, requestForm);
        queryWrapper.selectAll(EnStockTaskEntity.class);
        queryWrapper.eq(EnStockTaskEntity::getIsDel, 0);

        queryWrapper.orderByDesc(EnStockTaskEntity::getPlanStime, EnStockTaskEntity::getId);
        Page<EnStockTaskEntity> page = Page.of(requestForm.getPageNo(), requestForm.getPageSize());

        IPage<EnStockTaskEntity> iPage = baseMapper.selectJoinPage(page, EnStockTaskEntity.class, queryWrapper);
        page.setRecords(iPage.getRecords());
        page.setTotal(iPage.getTotal());
        return mapstruct.toVos(page);
    }

    @Override
    public Page<EnStockTaskVo> getOrderPage(RequestForm<EnStockTaskVo> requestForm) {
        EnStockTaskEntity entity = mapstruct.toEntity(requestForm.getEntity());
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = QueryMapperUtil.initQueryWrapper(entity, requestForm);
        queryWrapper.selectAll(EnStockTaskEntity.class);
        queryWrapper.eq(EnStockTaskEntity::getIsDel, 0);
        // 计划开始日期小于当前时间的显示
//        queryWrapper.le(EnStockTaskEntity::getPlanStime, new Date());
        queryWrapper.orderByDesc(EnStockTaskEntity::getPlanStime, EnStockTaskEntity::getId);
        Page<EnStockTaskEntity> page = Page.of(requestForm.getPageNo(), requestForm.getPageSize());

        IPage<EnStockTaskEntity> iPage = baseMapper.selectJoinPage(page, EnStockTaskEntity.class, queryWrapper);
        page.setRecords(iPage.getRecords());
        page.setTotal(iPage.getTotal());
        return mapstruct.toVos(page);
    }

    @Override
    public IPage<EnStockTaskDetailVo> getTaskDetailPage(RequestForm<EnStockTaskDetailVo> requestForm) {
        Page<EnStockTaskDetailVo> page = Page.of(requestForm.getPageNo(), requestForm.getPageSize());

        return taskEquipMapper.getTaskDetailPage(page, requestForm.getEntity());

    }

    @Override
    public Long count(RequestForm<EnStockTaskVo> requestForm) {
        EnStockTaskEntity entity = mapstruct.toEntity(requestForm.getEntity());
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = QueryMapperUtil.initQueryWrapper(entity, requestForm);
        queryWrapper.select(EnStockTaskEntity::getId);
        return baseMapper.selectCount(queryWrapper);
    }

    @Override
    public int insert(List<EnStockTaskVo> vos) {
        int result = 0;
        for (int i = 0, size = vos.size(); i < size; i++) {
            EnStockTaskVo taskVo = vos.get(i);
            taskVo.setCreateTime(new Date());
            // 1周期性 循环周期创建任务
            // 2非周期性  插入一条
            String sourceTaskNo = createTaskNo();
            if ("1".equals(taskVo.getTaskTypeNo())) {
                // 生成任务编号-做记录用 表里source_task_no一致的为一组
                taskVo.setSourceTaskNo(sourceTaskNo);
                taskVo.setIsPeriod("1");

                String taskName = taskVo.getTaskName();
                // 周期天数
                int period = Integer.parseInt(taskVo.getPeriod());
                // 周期截止日期
                Date periodEtime = taskVo.getPeriodEtime();
                // 初始计划开始时间
                Date planStime = taskVo.getPlanStime();
                // 初始计划结束时间
                Date planEtime = taskVo.getPlanEtime();
                // 周期内总天数
                int dayNum = DateUtils.daysBetween(planStime, periodEtime);
                // 循环次数
                int cycleNum = (int) Math.ceil((double) dayNum / period);

                for (int j = 0; j < cycleNum; j++) {
                    int addDays = j * period;
                    // 生成新的工单编号
                    String newTaskNo = createTaskNo();
                    taskVo.setTaskNo(newTaskNo);
                    taskVo.setTaskName(taskName + "-周期内" + (j + 1));
                    taskVo.setPlanStime(DateUtils.addDate(planStime, addDays));
                    taskVo.setPlanEtime(DateUtils.addDate(planEtime, addDays));
                    result += saveTaskAndEquip(taskVo);
                }
            } else {
                taskVo.setTaskNo(sourceTaskNo);
                result += saveTaskAndEquip(taskVo);
            }
        }
        return result;
    }


    @Override
    public int update(List<EnStockTaskVo> vos) {
        List<EnStockTaskEntity> entitys = mapstruct.toEntitys(vos);
        int result = 0;
        for (int i = 0, size = entitys.size(); i < size; i++) {
            EnStockTaskEntity entity = entitys.get(i);
            result += baseMapper.updateById(entity);

//            if (vos.get(i).getTaskEquipVoList() != null) {
//                saveTaskEquip(entity.getTaskNo(), vos.get(i).getTaskEquipVoList(), "UPDATE");
//            }
        }
        return result;
    }

    @Override
    public List<EnStockTaskEquipVo> getTaskEquipList(String taskNo) {
        MPJLambdaWrapper<EnStockTaskEquipEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(EnStockTaskEquipEntity.class);
        queryWrapper.eq(EnStockTaskEquipEntity::getTaskNo, taskNo);
        List<EnStockTaskEquipEntity> stockEquipEntities = taskEquipMapper.selectList(queryWrapper);

        return stockEquipEntities.stream().map(item -> {
            EnStockTaskEquipVo itemVo = equipMapstruct.toVo(item);
            itemVo.setStockNum("1");
            return itemVo;
        }).collect(Collectors.toList());
    }

    @Override
    public Page<TEnStockEquipVo> getEquipPage(RequestForm<TEnWzEquipVo> requestForm) {
        Page<TEnWzEquipEntity> page = Page.of(requestForm.getPageNo(), requestForm.getPageSize());

        TEnWzEquipEntity entity = wzEquipMapstruct.toEntity(requestForm.getEntity());
        MPJLambdaWrapper<TEnWzEquipEntity> queryWrapper = QueryMapperUtil.initQueryWrapper(entity, requestForm);
        queryWrapper.selectAll(TEnWzEquipEntity.class);
        Page<TEnStockEquipVo> stockEquipVoPage = (Page<TEnStockEquipVo>) wzEquipMapper.selectJoinPage(page, TEnStockEquipVo.class, queryWrapper);
        List<TEnStockEquipVo> stockEquipVos = stockEquipVoPage.getRecords().stream().map(item -> {
            item.setKcs(1);
            return item;
        }).collect(Collectors.toList());
        stockEquipVoPage.setRecords(stockEquipVos);

        return stockEquipVoPage;
    }

    @Override
    public TEnStockTaskProcessVo getTaskProcess(String taskNo) {
        TEnStockTaskProcessVo returnVo = new TEnStockTaskProcessVo();
        List<TEnTaskOperateVo> taskOperateVos = getBaseProcessList(taskNo);

        LambdaQueryWrapper<EnStockTaskOperatePtEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EnStockTaskOperatePtEntity::getTaskNo, taskNo);
        queryWrapper.orderByAsc(EnStockTaskOperatePtEntity::getOptStatus);
        List<EnStockTaskOperatePtEntity> taskOperateEntities = taskOperateMapper.selectList(queryWrapper);
        String optStatus = setProcessDateAndGetNodeStatus(taskOperateEntities, taskOperateVos);

        LambdaQueryWrapper<EnStockTaskEntity> enStockqueryWrapper = new LambdaQueryWrapper<>();
        enStockqueryWrapper.select(EnStockTaskEntity::getTaskStatus);
        enStockqueryWrapper.eq(EnStockTaskEntity::getTaskNo, taskNo);
        EnStockTaskEntity entity = enStockTaskMapper.selectOne(enStockqueryWrapper);
        this.setNodeAndFormatDate(entity.getTaskStatus(), taskOperateVos, returnVo);

        return returnVo;
    }

    /**
     * 获取基础流程list
     *
     * @param taskNo
     * @return
     */
    private List<TEnTaskOperateVo> getBaseProcessList(String taskNo) {
        LambdaQueryWrapper<EnStockTaskEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EnStockTaskEntity::getTaskNo, taskNo);
        EnStockTaskEntity taskEntity = baseMapper.selectOne(queryWrapper);

        List<TEnTaskOperateVo> processVos = new ArrayList<>();
        processVos.add(new TEnTaskOperateVo("工单编制", DateUtils.formatDate(taskEntity.getCreateTime(), DateUtils.DATE_TIME_24_FORMAT), 0, 1, "0", "1"));
        processVos.add(new TEnTaskOperateVo("派单", "", 0, 0, "1", "2"));
        processVos.add(new TEnTaskOperateVo("接单", "", 0, 0, "2", "3"));
        processVos.add(new TEnTaskOperateVo("现场盘点", "", 0, 0, "3", "4"));
        processVos.add(new TEnTaskOperateVo("质量评价", "", 0, 0, "4", "5"));
        processVos.add(new TEnTaskOperateVo("归档", "", 0, 0, "99", "7"));
        return processVos;
    }

    /**
     * 设置时间并且获取节点状态
     *
     * @param taskOperateEntities
     * @param taskOperateVos
     * @return
     */
    private String setProcessDateAndGetNodeStatus(List<EnStockTaskOperatePtEntity> taskOperateEntities, List<TEnTaskOperateVo> taskOperateVos) {
        String optStatus = "0";
        for (TEnTaskOperateVo process : taskOperateVos) {
            List<EnStockTaskOperatePtEntity> collect = taskOperateEntities.stream().filter(item -> process.getOptStatus().equals(item.getOptStatus())).collect(Collectors.toList());
            if (collect.isEmpty()) {
                continue;
            }
            optStatus = process.getOptStatus();
            process.setIsActive(1);
            process.setProcessDate(DateUtils.formatDate(collect.get(0).getOptTime(), DateUtils.DATE_TIME_24_FORMAT));
        }
        return optStatus;
    }

    /**
     * 设置是否此节点和格式化时间
     *
     * @param optStatus
     * @param taskOperateVos
     * @param processVo
     */
    private void setNodeAndFormatDate(String optStatus, List<TEnTaskOperateVo> taskOperateVos, TEnStockTaskProcessVo processVo) {
        String year = taskOperateVos.get(0).getProcessDate().substring(0, 4);
        int activeSteps = 0;
        for (int i = 0; i < taskOperateVos.size(); i++) {
            TEnTaskOperateVo process = taskOperateVos.get(i);
            Integer opt = Integer.parseInt(optStatus);
            Integer pro = Integer.parseInt(process.getOptStatus());

            //已归档不用闪烁
            if (optStatus.equals(process.getOptStatus())) {
                process.setIsNode(1);
                activeSteps = i + 1;
            }
            if (StringUtils.isBlank(process.getProcessDate())) {
                continue;
            }
            if (opt >= pro) {//!"0".equals(process.getOptStatus()) && year.equals(process.getProcessDate().substring(0, 4))
                // process.setProcessDate(process.getProcessDate().substring(5));
                process.setProcessDate(process.getProcessDate());
            } else {
                //year = process.getProcessDate().substring(0, 4);
                process.setProcessDate("");
            }
        }
        processVo.setActiveSteps(activeSteps);
        processVo.setOperateVoList(taskOperateVos);
    }

    @Override
    public int sendOrder(EnStockTaskVo vo) {
        EnStockTaskEntity taskEntity = mapstruct.toEntity(vo);
        taskEntity.setTaskStatus("1");
        taskEntity.setTaskStatusName("已派单未处理");
        taskEntity.setRunStatus("1");
        taskEntity.setRunStatusName("已派单");

        baseMapper.updateById(taskEntity);

        saveTaskOperate(vo, "1", "已派单", taskEntity.getSendTime());
        // TODO 派单到APP逻辑
        return 1;
    }

    private void mergePowerOrderParam(MPJLambdaWrapper<EnStockTaskEquipEntity> queryWrapper) {
        queryWrapper.select(TEnWzEquipEntity::getSbbm);
        queryWrapper.select(TEnWzEquipEntity::getSbmc);
        queryWrapper.select(TEnWzEquipEntity::getYxztmc);
        queryWrapper.select(TEnWzEquipEntity::getSblxbm);
        queryWrapper.select(TEnWzEquipEntity::getSblxmc);
        queryWrapper.select(TEnWzEquipEntity::getJlfsmc);
        queryWrapper.select(TEnWzEquipEntity::getSbgg);
        queryWrapper.select(TEnWzEquipEntity::getXh);
        queryWrapper.select(TEnWzEquipEntity::getGldwmc);
        queryWrapper.select(TEnWzEquipEntity::getCcrq);
        queryWrapper.select(TEnWzEquipEntity::getCcbm);
        queryWrapper.select(TEnWzEquipEntity::getSskfbm);
//        queryWrapper.selectAs(EnStockTaskEquipEntity::getStockNum, "kcs");
//        queryWrapper.selectAs(EnStockTaskEquipEntity::getActualNum, "sjs");
        queryWrapper.innerJoin(EnStockTaskEquipEntity.class, EnStockTaskEquipEntity::getEquipNo, TEnWzEquipEntity::getSbbm);
        queryWrapper.orderByAsc(EnStockTaskEquipEntity::getEquipNo);
    }

    /**
     * 生成工单编号 年月日时分秒毫秒+4位随机数
     *
     * @return 编号
     */
    private String createTaskNo() {
        // 当前时间字符串-到毫秒
        String dateStr = DateUtils.formatDate(new Date(), DateUtils.DATE_MSEC_FORMAT2);
        // 随机数
        Random rand = new Random();
        String num4Str = String.format("%04d", rand.nextInt(1000));

        return dateStr + num4Str;
    }

    /**
     * 保存任务和设备
     *
     * @param taskVo
     * @return
     */
    private int saveTaskAndEquip(EnStockTaskVo taskVo) {
        int result = 0;
        EnStockTaskEntity taskEntity = mapstruct.toEntity(taskVo);
        result = baseMapper.insert(taskEntity);
//         保存设备
//        saveTaskEquip(taskVo.getTaskNo(), taskVo.getTaskEquipVoList(), "ADD");
//         保存到任务操作表
        saveTaskOperate(taskVo, "0", "工单编制", taskVo.getCreateTime());
        return result;
    }

    /**
     * 保存任务操作
     *
     * @param taskVo        taskVo
     * @param optStatus     optStatus
     * @param optStatusName optStatusName
     * @param optTime       optTime
     */
    private void saveTaskOperate(EnStockTaskVo taskVo, String optStatus, String optStatusName, Date optTime) {
        EnStockTaskOperatePtEntity operateEntity = new EnStockTaskOperatePtEntity();
        operateEntity.setTaskNo(taskVo.getTaskNo());
        operateEntity.setOptStatus(optStatus);
        operateEntity.setOptStatusName(optStatusName);
        operateEntity.setOptTime(optTime);

        taskOperateMapper.insert(operateEntity);
    }

    /**
     * 设备保存
     *
     * @param taskNo          任务号
     * @param taskEquipVoList 任务设备
     * @param type            ADD/UPDATE
     */
    private void saveTaskEquip(String taskNo, List<EnStockTaskEquipVo> taskEquipVoList, String type) {
        // 设备修改 先删除再保存
        if ("UPDATE".equals(type)) {
            LambdaQueryWrapper<EnStockTaskEquipEntity> deleteWrapper = new LambdaQueryWrapper();
            deleteWrapper.eq(EnStockTaskEquipEntity::getTaskNo, taskNo);
            equipService.remove(deleteWrapper);
        }
        // 保存任务设备
        List<EnStockTaskEquipEntity> equipEntities = equipMapstruct.toEntitys(taskEquipVoList);
        if (CollectionUtils.isNotEmpty(equipEntities)) {
            List<EnStockTaskEquipEntity> insertEntities = equipEntities.stream().map(item -> {
                item.setTaskNo(taskNo);
                return item;
            }).collect(Collectors.toList());

            equipService.saveBatch(insertEntities);
        }
    }

    /**
     * 盘点任务操作记录保存
     *
     * @param taskVo        taskVo
     * @param optStatus     optStatus
     * @param optStatusName optStatusName
     */
    @Override
    public void saveTaskOperate(EnStockTaskVo taskVo, String optStatus, String optStatusName) {
        this.saveTaskOperate(taskVo, optStatus, optStatusName, taskVo.getCreateTime());
    }

    /**
     * 根据任务编码获取缺陷隐患列表
     *
     * @param taskNo 任务编码
     * @return
     */
    @Override
    public List<EnStockEquipDefectVo> getTaskDefectList(String taskNo) {
        MPJLambdaWrapper<EnStockEquipDefectEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(EnStockEquipDefectEntity.class);
        queryWrapper.eq(EnStockEquipDefectEntity::getTaskNo, taskNo);
        List<EnStockEquipDefectEntity> stockEquipEntities = equipDefectMapper.selectList(queryWrapper);

        return stockEquipEntities.stream().map(item -> {
            return equipDefectMapstruct.toVo(item);
        }).collect(Collectors.toList());
    }

    /**
     * 获取工单编号
     *
     * @return
     */
    @Override
    public String getTaskNo() {
        // 当前时间字符串-到毫秒
        String dateStr = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
        // 随机数
        Random rand = new Random();
        String num4Str = String.format("%04d", rand.nextInt(1000));
        return dateStr + num4Str;
    }

    /**
     * 盘点设备统计
     *
     * @param taskNo 任务编码
     * @return
     */
    @Override
    public List<StockEquipStatisticsVo> getEquipStatisticsByTaskNo(String taskNo) {
        MPJLambdaWrapper<EnStockTaskEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.eq(EnStockTaskEntity::getTaskNo, taskNo);
        queryWrapper.selectAll(EnStockTaskEntity.class);
        List<EnStockTaskEntity> entities = baseMapper.selectList(queryWrapper);

        MPJLambdaWrapper<TEnWzSblxEntity> equipTypeWrapper = new MPJLambdaWrapper<>();
        equipTypeWrapper.selectAs(TEnWzSblxEntity::getId, "equipTypeNo");
        equipTypeWrapper.selectAs(TEnWzSblxEntity::getName, "equipTypeName");
        equipTypeWrapper.eq(TEnWzSblxEntity::getPid, "1000");
        equipTypeWrapper.in(TEnWzSblxEntity::getId, entities.get(0).getStockType().split(","));
        equipTypeWrapper.orderByAsc(TEnWzSblxEntity::getOrderNo);
        List<StockEquipStatisticsVo> resultList = sblxMapper.selectJoinList(StockEquipStatisticsVo.class, equipTypeWrapper);
        this.setTaskEquipStatistics(taskNo, "scanNum", "1", resultList);
        this.setTaskEquipStatistics(taskNo, "manualNum", "2", resultList);
        List<StockEquipStatisticsVo> stockEquipStatisticsVos
                = this.setStockEquipStatistics(taskNo, StrUtil.nullToDefault(resultList.get(0).getWarehouseNo(), ""), resultList);
        resultList.forEach(taskEquipStatistics -> {
            String equipTypeNo = taskEquipStatistics.getEquipTypeNo();
            stockEquipStatisticsVos.forEach(stockEquipStatistics -> {
                String equipTypeNo1 = stockEquipStatistics.getEquipTypeNo();
                if (equipTypeNo.equals(equipTypeNo1)) {
                    BeanUtil.copyProperties(stockEquipStatistics, taskEquipStatistics, "taskNo", "warehouseNo", "equipTypeNo", "equipTypeName", "scanNum", "manualNum", "totalNum");
                }
            });
        });
        return resultList;
    }

    /**
     * 盘点设备统计的后三列
     *
     * @param taskNo      盘点任务编号
     * @param warehouseNo 盘点库房编号
     * @param resultList  只为了获取其中的所有设备类型
     * @return
     */
    private List<StockEquipStatisticsVo> setStockEquipStatistics(String taskNo, String warehouseNo, List<StockEquipStatisticsVo> resultList) {
        MPJLambdaWrapper<EnWzEquipLogEntity> equipLogWrapper = new MPJLambdaWrapper<>();
        equipLogWrapper.selectAs(EnWzEquipLogEntity::getSblxbm, "equipTypeNo");
        equipLogWrapper.selectAs(EnWzEquipLogEntity::getCcbm, "equipFactoryNo");
        equipLogWrapper.eq(EnWzEquipLogEntity::getSskfbm, warehouseNo);
        equipLogWrapper.eq(EnWzEquipLogEntity::getTaskNo, taskNo);
        equipLogWrapper.eq(EnWzEquipLogEntity::getSfsc, "0");
        Map<String, List<String>> equipLogEquipNoMap = this.getEquipTypeEquipNoMap(equipLogMapper.selectJoinList(StockEquipTypeEquipNoVo.class, equipLogWrapper), resultList);

        MPJLambdaWrapper<EnStockTaskEquipEntity> equipTaskWrapper = new MPJLambdaWrapper<>();
        equipTaskWrapper.selectAs(EnStockTaskEquipEntity::getEquipTypeNo, "equipTypeNo");
        equipTaskWrapper.selectAs(EnStockTaskEquipEntity::getFactoryNo, "equipFactoryNo");
        equipTaskWrapper.eq(EnStockTaskEquipEntity::getTaskNo, taskNo);
        Map<String, List<String>> equipTaskEquipNoMap = this.getEquipTypeEquipNoMap(taskEquipMapper.selectJoinList(StockEquipTypeEquipNoVo.class, equipTaskWrapper), resultList);

        List<StockEquipStatisticsVo> equipStatisticsVos = new ArrayList<>();
        equipLogEquipNoMap.forEach((logKey, logValue) -> {
            StockEquipStatisticsVo statisticsVo = new StockEquipStatisticsVo();
            List<String> tempLogValue = logValue.stream().collect(Collectors.toList());
            equipTaskEquipNoMap.forEach((taskKey, taskValue) -> {
                if (logKey.equals(taskKey)) {
                    statisticsVo.setEquipTypeNo(logKey);
                    statisticsVo.setStockLogNum(logValue.size());
                    statisticsVo.setStockTaskNum(taskValue.size());
                    logValue.removeAll(taskValue);
                    statisticsVo.setStockLogDiffNum(logValue.size());
                    statisticsVo.setStockLogDiffList(logValue);
                    statisticsVo.setMatchNum(tempLogValue.size() - logValue.size());
                    taskValue.removeAll(tempLogValue);
                    statisticsVo.setStockTaskDiffNum(taskValue.size());
                    statisticsVo.setStockTaskDiffList(taskValue);
                    statisticsVo.setDiffNum(logValue.size() + taskValue.size());
                }
            });
            equipStatisticsVos.add(statisticsVo);
        });
        return equipStatisticsVos;
    }

    /**
     * 获取equipTypeNo->equipNo(出厂编码) 集合List
     *
     * @param vos 参数
     * @return
     */
    private Map<String, List<String>> getEquipTypeEquipNoMap(List<StockEquipTypeEquipNoVo> vos, List<StockEquipStatisticsVo> resultList) {
        Map<String, List<String>> equipTypeEquipNoMap = new HashMap<>();
        resultList.forEach(stockEquipStatisticsVo -> equipTypeEquipNoMap.put(stockEquipStatisticsVo.getEquipTypeNo(), new ArrayList<>()));
        if (vos.size() > 0) {
            vos.forEach(equipTypeEquipNoVo -> {
                String equipTypeNo = equipTypeEquipNoVo.getEquipTypeNo();
                List<String> tempEquipFactoryNos = new ArrayList<>();
                if (equipTypeEquipNoMap.containsKey(equipTypeNo)) {
                    tempEquipFactoryNos = equipTypeEquipNoMap.get(equipTypeNo);
                }
                tempEquipFactoryNos.add(equipTypeEquipNoVo.getEquipFactoryNo());
                equipTypeEquipNoMap.put(equipTypeNo, tempEquipFactoryNos);
            });
        }
        return equipTypeEquipNoMap;
    }

    /**
     * 盘点设备统计的前三列 scanNum/manualNum/totalNum
     *
     * @param taskNo          盘点任务编号
     * @param stockMethodName scanNum/manualNum
     * @param stockMethodNo   1/2
     * @return
     */
    private void setTaskEquipStatistics(String taskNo, String stockMethodName, String stockMethodNo, List<StockEquipStatisticsVo> resultList) {
        MPJLambdaWrapper<EnStockTaskEquipEntity> equipStatisticsWrapper = new MPJLambdaWrapper<>();
        equipStatisticsWrapper.select(EnStockTaskEquipEntity::getTaskNo);
        equipStatisticsWrapper.select(EnStockTaskEntity::getWarehouseNo);
        equipStatisticsWrapper.select(EnStockTaskEquipEntity::getEquipTypeName);
        equipStatisticsWrapper.select(EnStockTaskEquipEntity::getEquipTypeNo);
        equipStatisticsWrapper.selectCount(EnStockTaskEquipEntity::getEquipNo, stockMethodName);
        equipStatisticsWrapper.innerJoin(EnStockTaskEntity.class, EnStockTaskEntity::getTaskNo, EnStockTaskEquipEntity::getTaskNo);
        equipStatisticsWrapper.eq(EnStockTaskEquipEntity::getTaskNo, taskNo);
        equipStatisticsWrapper.eq(EnStockTaskEquipEntity::getStockMethodNo, stockMethodNo);
        equipStatisticsWrapper.groupBy(EnStockTaskEquipEntity::getTaskNo, EnStockTaskEquipEntity::getEquipTypeName, EnStockTaskEquipEntity::getEquipTypeNo);
        equipStatisticsWrapper.groupBy(EnStockTaskEntity::getWarehouseNo);
        List<StockEquipStatisticsVo> statisticsEntities = this.taskEquipMapper.selectJoinList(StockEquipStatisticsVo.class, equipStatisticsWrapper);
        resultList.forEach(stockEquipStatisticsVo -> {
            String equipTypeNo = stockEquipStatisticsVo.getEquipTypeNo();
            String taskNo1 = "", warehouseNo = "";
            if (statisticsEntities.size() > 0) {
                taskNo1 = statisticsEntities.get(0).getTaskNo();
                warehouseNo = statisticsEntities.get(0).getWarehouseNo();
                statisticsEntities.forEach(statisticsEntity -> {
                    String scanEquipTypeNo = statisticsEntity.getEquipTypeNo();
                    if (equipTypeNo.equals(scanEquipTypeNo)) {
                        if ("1".equals(stockMethodNo)) {
                            stockEquipStatisticsVo.setScanNum(statisticsEntity.getScanNum());
                            stockEquipStatisticsVo.setTotalNum(stockEquipStatisticsVo.getScanNum() + statisticsEntity.getManualNum());
                        } else if ("2".equals(stockMethodNo)) {
                            stockEquipStatisticsVo.setManualNum(statisticsEntity.getManualNum());
                            stockEquipStatisticsVo.setTotalNum(stockEquipStatisticsVo.getScanNum() + statisticsEntity.getManualNum());
                        }
                    }
                });
            }
            stockEquipStatisticsVo.setTaskNo(taskNo1);
            stockEquipStatisticsVo.setWarehouseNo(warehouseNo);
        });
    }

    /**
     * 分页查询设备列表根据任务编号
     *
     * @param requestForm
     * @return
     */
    @Override
    public Page<EnStockTaskEquipVo> getTaskEquipListPage(RequestForm<StockEquipStatisticsVo> requestForm) {
        Page<EnStockTaskEquipEntity> page = Page.of(requestForm.getPageNo(), requestForm.getPageSize());
        MPJLambdaWrapper<EnStockTaskEquipEntity> queryWrapper = new MPJLambdaWrapper<>();
        queryWrapper.selectAll(EnStockTaskEquipEntity.class);
        queryWrapper.eq(EnStockTaskEquipEntity::getTaskNo, requestForm.getEntity().getTaskNo());
        queryWrapper.eq(EnStockTaskEquipEntity::getEquipTypeNo, requestForm.getEntity().getEquipTypeNo());
        return (Page<EnStockTaskEquipVo>) taskEquipMapper.selectJoinPage(page, EnStockTaskEquipVo.class, queryWrapper);
    }

    @SneakyThrows
    @Override
    public void exportExcel(HttpServletResponse response, RequestForm<EnStockTaskDetailVo> requestForm) {
        //设置信息头，告诉浏览器内容为excel类型
        response.setHeader("content-Type", "application/vnd.ms-excel");
        //文件名称
        String fileName = "盘点任务详情列表.xls";
        //sheet名称
        String sheetName = "盘点任务详情列表";
        fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8);
        //设置下载名称
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        //获取到业务数据
        IPage<EnStockTaskDetailVo> page = this.getTaskDetailPage(requestForm);
        List<EnStockTaskDetailVo> records = page.getRecords();
        List<EnStockTaskDetailExportExcelVo> excelVos = new ArrayList<>(records.size());
        records.forEach(taskDetailVo -> {
            EnStockTaskDetailExportExcelVo excelVo = new EnStockTaskDetailExportExcelVo();
            BeanUtil.copyProperties(taskDetailVo, excelVo);
            if ("1".equals(taskDetailVo.getIfTest())) {
                excelVo.setIfTest("是");
            } else {
                excelVo.setIfTest("否");
            }
            excelVos.add(excelVo);
        });
        //导入excel
        ExcelUtil<EnStockTaskDetailExportExcelVo> util = new ExcelUtil<>(EnStockTaskDetailExportExcelVo.class);
        util.exportExcel(response, excelVos, sheetName);
    }

}
